<?php defined('SYSPATH') or die('No direct script access.');

class Model_Product extends ORM
{ 
    const PRODUCTS_PER_PAGE = 60;
    protected $_reload_on_wakeup = false;
    
    public static function get_available_prices()
    {
        return array(
            array('from' => null,  'to' => 500),
            array('from' => 500,   'to' => 1000),
            array('from' => 1000,  'to' => 1500),
            array('from' => 1500,  'to' => 2000),
            array('from' => 2000,  'to' => 3000),
            array('from' => 3000,  'to' => 4000),
            array('from' => 4000,  'to' => 5000),
            array('from' => 5000,  'to' => 7000),
            array('from' => 7000,  'to' => 10000),
            array('from' => 10000, 'to' => 15000),
            array('from' => 15000, 'to' => null),
        );
    }
    
    public static function get_prices(Model_Category $category, $brand = null, $color = null, $composition = null, $season = null, $shop = null)
    {
        $ids = array(); 
        if ($category->childs) {
            $ids = explode(',', $category->childs);    
        }
        $ids[] = $category->id;
        
        $brand_id = $brand;
        if (is_array($brand)) {
            $brand_id = $brand['id'];   
        }
        
        $color_id = $color;
        if (is_array($color)) {
            $color_id = $color['id'];    
        }
        
        $composition_id = $composition;
        if (is_array($composition)) {
            $composition_id = $composition['id'];    
        }
        
        $season_id = $season;
        if (is_array($season)) {
            $season_id = $season['id'];    
        }
        
        $shop_id = $shop;
        if (is_array($shop)) {
            $shop_id = $shop['id'];   
        }
        
        if ($prices = Cache::instance()->get('category_prices_'.$category->id.'_'.$brand_id.'_'.$color_id.'_'.$composition_id.'_'.$season_id.'_'.$shop_id)) {
            return $prices;
        } 
        
        $subqueries = array();
        $all_prices = self::get_available_prices();
        foreach ($all_prices as $price) {
            $subquery = DB::select(DB::expr('COUNT( * )'))
                            ->from('products')
                            ->where('category_id', 'IN', $ids)
                            ->where('available', '=', 1);
                            
            if ($price['from']) {
                $subquery->where('price', '>=', $price['from']);    
            }
            if ($price['to']) {
                $subquery->where('price', '<=', $price['to']); 
            }
                            
            if ($brand_id) {
                $subquery->where('brand_id', '=', $brand_id); 
            } 
            
            if ($color_id) {
                $subquery->join('product_colors', 'LEFT')
                            ->on('product_colors.product_id', '=', 'products.id')
                            ->where('product_colors.color_id', '=', $color_id);   
            }         
        
            if ($composition_id) {
                $subquery->join('product_compositions', 'LEFT')
                            ->on('product_compositions.product_id', '=', 'products.id')
                            ->where('product_compositions.composition_id', '=', $composition_id);   
            }
            
            if ($season_id) {
                $subquery->join('product_seasons', 'LEFT')
                            ->on('product_seasons.product_id', '=', 'products.id')
                            ->where('product_seasons.season_id', '=', $season_id);   
            }
            
            if ($shop_id) {
                $subquery->where('shop_id', '=', $shop_id);    
            }
            $subqueries[] = "(".$subquery->__toString().") AS '".$price['from']."_".$price['to']."'";    
        }
        
        $stat = DB::query(Database::SELECT, "
            SELECT ".implode(',', $subqueries)." FROM products LIMIT 1
        ")->execute()->as_array();
        $stat = $stat[0];
        
        $prices = array();
        foreach ($all_prices as $price) {
            $value = $price;
            $value['count'] = $stat[$price['from'].'_'.$price['to']];
            if ($value['count']) {
                $prices[] = $value;   
            }  
        }
        
        Cache::instance()->set('category_prices_'.$category->id.'_'.$brand_id.'_'.$color_id.'_'.$composition_id.'_'.$season_id.'_'.$shop_id, $prices);
        return $prices;
    }
    
    public function get_products_for_main()
    {
        if ($products = Cache::instance()->get('main_products')) {
            return $products;
        }
        
        $products = array();
        $categories = ORM::factory('category')->get_main_categories();
        foreach ($categories as $category) {
			$ids = array();
			if ($category->childs) {
				$ids   = explode(',', $category->childs);
			}
            $ids[] = $category->id;
            $top = $this->_get_products_query()
                        ->where('category_id', 'IN', $ids)
                        ->order_by('sort', 'DESC')
                        ->limit(4)
                        ->find_all()
                        ->as_array(); 
            $products[$category->id] = $top;    
        }
        
        Cache::instance()->set('main_products', $products);
        return $products;    
    }
    
    public function get_products($category = null, $brand = null, $color = null, $composition = null, $season = null, $shop = null, $price = null, $page = null, $count = false)
    {        
        $category_id = $category;
        if ($category instanceof Model_Category) {
            $category_id = $category->id;
            $categories  = null;
            if ($category->childs) {
                $categories = explode(',', $category->childs);
                $categories[] = $category->id; 
            } 
        }
        
        $brand_id = $brand;
        if ($brand instanceof Model_Brand) {
            $brand_id = $brand->id;    
        }
        
        $color_id = $color;
        if (is_array($color)) {
            $color_id = $color['id'];   
        }
        
        $composition_id = $composition;
        if (is_array($composition)) {
            $composition_id = $composition['id'];    
        }
        
        $season_id = $season;
        if (is_array($season)) {
            $season_id = $season['id'];    
        }
        
        $shop_id = $shop;
        if ($shop instanceof Model_Shop) {
            $shop_id = $shop->id;    
        }
        
        $from_price = $to_price = null;
        if (isset($price['from']) && $price['from']) {
            $from_price = $price['from'];    
        }
        if (isset($price['to']) && $price['to']) {
            $to_price = $price['to'];    
        }
        
        if ($products = Cache::instance()->get('products_'.$category_id.'_'.$brand_id.'_'.$color_id.'_'.$composition_id.'_'.$season_id.'_'.$shop_id.'_'.$from_price.'_'.$to_price.'_'.$page.'_'.$count)) {
            return $products;
        }
         
        $query = $this->_get_products_query(); 
        
        if ($category_id) {
            if ($categories) {
                $query->where('category_id', 'IN', $categories);    
            } else {
                $query->where('category_id', '=', $category_id);
            }
        }
        
        if ($brand_id) {
            $query->where('brand_id', '=', $brand_id);    
        }
        
        if ($color_id) {
            $query->join('product_colors', 'LEFT')
                  ->on('product_colors.product_id', '=', 'product.id')
                  ->where('product_colors.color_id', '=', $color_id);   
            //$query->where('id', 'IN', DB::expr("(SELECT product_id FROM product_colors WHERE color_id = {$color_id})"));  
        }
        
        if ($composition_id) {
            $query->join('product_compositions', 'LEFT')
                  ->on('product_compositions.product_id', '=', 'product.id')
                  ->where('product_compositions.composition_id', '=', $composition_id); 
            //$query->where('id', 'IN', DB::expr("(SELECT product_id FROM product_compositions WHERE composition_id = {$composition_id})"));   
        }
        
        if ($season_id) {
            $query->join('product_seasons', 'LEFT')
                  ->on('product_seasons.product_id', '=', 'product.id')
                  ->where('product_seasons.season_id', '=', $season_id); 
            //$query->where('id', 'IN', DB::expr("(SELECT product_id FROM product_seasons WHERE season_id = {$season_id})"));   
        }
        
        if ($shop_id) {
            $query->where('shop_id', '=', $shop_id);    
        }
        
        if ($from_price) {
            $query->where('price', '>=', $from_price);    
        }
        if ($to_price) {
            $query->where('price', '<=', $to_price); 
        }
        
        $query->order_by('sort', 'DESC');
        
        if ($count) {
            $result = $query->count_all();
            Cache::instance()->set('products_'.$category_id.'_'.$brand_id.'_'.$color_id.'_'.$composition_id.'_'.$season_id.'_'.$shop_id.'_'.$from_price.'_'.$to_price.'_'.$page.'_'.$count, $result);
            return $result;
        }        
            
        if ($page) {
            $_count = self::get_products_per_page();
            $offset = ($page - 1) * $_count;
            $query->offset($offset)->limit($_count);    
        }
        
        $products = $query->find_all()->as_array();  
        Cache::instance()->set('products_'.$category_id.'_'.$brand_id.'_'.$color_id.'_'.$composition_id.'_'.$season_id.'_'.$shop_id.'_'.$from_price.'_'.$to_price.'_'.$page.'_'.$count, $products); 
        return $products;
    }    
    
    public function get_related_products($count = 5)
    {
        return $this->_get_products_query()
            ->where('category_id', '=', $this->category_id)
            ->and_where('id', '!=', $this->id)
            ->order_by(DB::expr('RAND()'))
            ->limit($count)
            ->find_all();
    }
    
    public static function get_products_per_page()
    {
        return self::PRODUCTS_PER_PAGE;
    }
    
    public function get_product_data()
    {
        $data = DB::select()
                    ->from('product_data')
                    ->where('product_id', '=', $this->id)
                    ->execute()
                    ->as_array();
        if (isset($data[0])) {
            return $data[0];
        }
        return array(
            'description' => null,
            'images'      => null,
            'params'      => null,
        );
    }
    
    public function extract_specs($product_data = null)
    {
        if (!$product_data) {
            $product_data = $this->get_product_data();
        }
        
        $specs     = array();
        /*if (!in_array($this->shop_id, array(1001, ))) {      
            $tmp_specs = explode("\n", $this->description);
            foreach ($tmp_specs as $item) {
                try {
                    list($name, $value) = explode(':', $item);
                    $name  = str_replace('- ', '', trim($name));
                    $value = trim($value);
                    $specs[$name] = $value;
                } catch (Exception $e) {
                    
                }    
            }
        }*/
        
        if ($product_data['params']) {
            foreach (json_decode($product_data['params'], true) as $name => $value) {
                $specs[$name] = $value;    
            }
        } 
        return $specs;
    }
    
    public function get_image()
    {
        $image = '';
        if ($this->shop_id == 4102) {    // Wildberries
            $image = $this->picture;    
        } else {
            $image = $this->picture_orig ;    
        }   
        return $image; 
    }
    
    public function get_url()
    {
        /*if (in_array($this->shop_id, array(4102))) {
            $url  = $this->_get_clean_url();
            $rand = mt_rand(0, 100);     
            if ($rand < 50) {       // admitad
                $pattern = 'http://ad.admitad.com/goto/1d9ed345ddea57d2938cdc28f2033d/?ulp=%url%&subid=%subaccount%';       
            } else {                // actionpay
                $pattern = 'http://n.actionpay.ru/click/52446a13fc3f5b858c000031/54232/%subaccount%/url=%url%';    
            }
                  
            $subid = $this->id;
            if (isset($_COOKIE['subid']) && $_COOKIE['subid']) {
                $subid = $_COOKIE['subid'].'_'.$subid;
            }
            return str_replace(array('%url%', '%subaccount%'), array($url, $subid), $pattern);
        } */   
           
        $url   = $this->url; 
        $subid = Model_Main::get_subid($this);     
        if (strstr($url, 'actionpay.ru') !== false) {
            $url = str_replace('/subaccount/', '/'.$subid.'/', $url);
        }
        if (strstr($url, 'admitad.com') !== false) {
            $url = str_replace('/?ulp=', '/subid/'.$subid.'/?ulp=', $url);
        } 
        return $url; 
    }
    
    protected function _get_clean_url()
    {
        $url = $this->url;
        if (strstr($url, 'admitad.com') !== false) {
            $delimeter = '?ulp=';
            $pos = strpos($url, $delimeter) + strlen($delimeter);
            $url = substr($url, $pos);
            $url = str_replace(array('%3A', '%2F'), array(':', '/'), $url);
        }
        return $url;
    }
    
    protected function _get_products_query()
    {
        return ORM::factory('product')->where('available', '=', 1);
    }
    
    public function process_params()
    {
        /*
        515     Quelle          цвет
        1001    Lamoda          цвет, материал, сезон
        1186    Proskater       цвет
        1326    TOPBRANDS       цвет, материал
        1477    ShopTime        -
        1757    BUTIK           цвет
        2775    MEXX            -
        2777    TomTailor       -
        3761    SHOWROOMS       материал
        4102    Wildberries     цвет, материал (состав), сезон, стиль
        */
        
        $_params = $this->extract_specs();
        $params  = array();
        if ($_params) {
            foreach ($_params as $name => $value) {
                $value = mb_strtolower(trim($value));
                $name  = mb_strtolower($name);
                $params[$name] = $value;                         
            }
        }
        
        $color = array(); $_color = null;
        $composition = array(); $_composition = null;
        $season = array(); $_season = null;
        
        if ($this->shop_id == 515) {       
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            }                       
        } else if ($this->shop_id == 1001) {
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            }
            if (isset($params['внешний материал'])) {
                $_composition = $params['внешний материал'];
            }
            if (isset($params['сезонность'])) {
                $_season = $params['сезонность'];
                if ($_season == 'мульти') {
                    $season[] = Model_Season::MULTI_SEASON;
                }
            }           
        } else if ($this->shop_id == 1186) {
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            }     
        } else if ($this->shop_id == 1326) {
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            } 
            if (isset($params['материал'])) {
                $_composition = $params['материал'];
            }     
        } else if ($this->shop_id == 1477) {
                
        } else if ($this->shop_id == 1757) {
            $_color = null;
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            }     
        } else if ($this->shop_id == 2775) {
                
        } else if ($this->shop_id == 2777) {
                
        } else if ($this->shop_id == 3761) {
            if (isset($params['материал'])) {
                $_composition = $params['материал'];
            }        
        } else if ($this->shop_id == 4102) {
            if (isset($params['цвет'])) {
                $_color = $params['цвет'];
            }
            if (isset($params['состав'])) {
                $_composition = $params['состав'];
            } 
            if (isset($params['сезон'])) {
                $_season = $params['сезон'];
            }   
        }
        
        if (!$color && $_color) {
            foreach (Model_Color::$color_options as $id => $item) {
                if (strstr($_color, $item['name']) !== false) {
                    $color[] = $id;   
                }    
            }    
        }
        
        if (!$composition && $_composition) {
            foreach (Model_Composition::$composition_options as $id => $item) {
                if (strstr($_composition, $item['name']) !== false) {
                    $composition[] = $id;  
                }    
            }    
        }
        
        if (!$season && $_season) {
            foreach (Model_Season::$season_options as $id => $item) {
                if (strstr($_season, $item['name']) !== false) {
                    $season[] = $id;   
                }    
            }    
        }
        
        foreach ($color as $color_id) {
            try { 
                DB::insert('product_colors', array('product_id', 'color_id'))
                    ->values(array($this->id, $color_id))
                    ->execute();
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                } else {
                    die($e->getMessage());
                }
            }   
        }
        
        foreach ($composition as $composition_id) {
            try { 
                DB::insert('product_compositions', array('product_id', 'composition_id'))
                    ->values(array($this->id, $composition_id))
                    ->execute();
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                } else {
                    die($e->getMessage());
                }
            }   
        }
        
        foreach ($season as $season_id) {
            try { 
                DB::insert('product_seasons', array('product_id', 'season_id'))
                    ->values(array($this->id, $season_id))
                    ->execute();
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                } else {
                    die($e->getMessage());
                }
            }   
        }
        
        $this->is_processed = 1;
        $this->save();
    }
    
    public function search($query, $page = 1, $is_test = false)
    {
        $query = self::get_clean_search_query($query);
        $query = str_replace(
            array(' в ', 'для полных', 'для детей', 'для женщин', 'шапок', 'норковую', 'штаны'),
            array(' ', 'больших размеров', 'детские', 'женские', 'шапки', 'норка', 'брюки'),
            $query
        );
        
        $stop_words = array(
            'дешев', 'дорог', 'доставк', 'заказ', 'магазин', 'интернет', 'купить', 'куплю', 'москв', 'продаж', 'цен', 'скидк', 'где', 'можно',
            'спб', 'розниц', 'наложенны', 'платеж', 'через', 'хочу', 'форум', 'оригинал', 'бренд', 'онлайн', 'какие', 'каталог', '2012', '2013', '2014',
            'лучш', 'фото', 'новый', 'фирм', 'элитн', 'настоящ', 'официальн', 'сайт', 'классный', 'импортный', 
            
            'красноярск', 'екатеринбург', 'челябинск', 'ярославл', 'стамбул', 'тюмен', 'питер', 'омск', 'киров', 'тул', 'саратов', 'харьков',
            'нижн', 'новгород', 'новосибирск', 'перм', 'воронеж', 'ростов', 'уф', 'краснодар', 'санкт', 'петербург', 'самар', 'казан', 'иркутск',
            'хабаровск', 'киров', 'ижевск', 'барнаул', 'кемеров', 'луганск', 'твер', 'липецк', 'волгоград', 'пенз', 'костром', 'ульяновск',
            'владимир', 'николаев', 'витебск', 'курск', 'тольятти', 'кривой рог', 'кривом рогу', 'сургут', 'чит', 'белгород', 'иваново', 'брянск',
            'курган', 'смоленск', 'тамбов', 'могилев', 'калининград', 'хмельницк', 'владивосток', 'саранск', 
        );
        
        $countries = array(
            'итальянск' => 'италия',
            'российск'  => 'россия',
            'китайск'   => 'китай',
            'канадск'   => 'канада',
            'немецк'    => 'германия',
            'японск'    => 'япония',
            'шведск'    => 'швеция',
            'польск'    => 'польша',
            'финск'     => 'финляндия',
            'турецк'    => 'турция',
        );
        
        $words       = explode(' ', $query);
        $clean_query = array();
        foreach ($words as $word) {
            $word  = trim($word);
            $found = false;
            foreach ($stop_words as $stop_word) {
                if (strstr($word, $stop_word) !== false) {
                    $found = true;
                    break;
                }    
            }    
            if (!$found) {
                $found = false;
                foreach ($countries as $first => $second) {
                    if (strstr($word, $first) !== false) {
                        $clean_query[] = $second;
                        $found = true;
                        break;
                    }    
                }
                if (!$found) {
                    $clean_query[] = $word;   
                }
            }
        }
        $clean_query = implode(' ', $clean_query);
        
        $limit  = self::get_products_per_page();
        $offset = 0;
        if ($page) {
            $limit = self::get_products_per_page();
            $offset = ($page - 1) * $limit;   
        }
        
        // создаем инстанц клиента
        $cl = new Library_SphinxClient();
         
        // настройки
        $cl->SetServer("localhost", 9312);
        $cl->SetConnectTimeout(5);
        $cl->SetLimits($offset, $limit);
        $cl->SetArrayResult(true);
        $cl->SetFieldWeights(array (
            'category_name'  => 100,
            'category_type'  => 80,
            'product_name'   => 70,
            'brand_synonyms' => 70,
            'description'    => 70,
            'product_params' => 70,
            'brand_name'     => 10,
        )); 
        //$cl->SetSortMode(SPH_SORT_EXPR, 'product_sort DESC, product_price ASC');
        //$cl->SetSortMode(SPH_SORT_ATTR_DESC, 'product_sort');
        
        //$cl->SetRankingMode(SPH_RANK_PROXIMITY_BM25);
        //$cl->SetMatchMode(SPH_MATCH_ANY);
        
        $result = $cl->Query($clean_query);
        
        $products = array();
        $count    = 0;
        if ($result) {
            if ($is_test) {
                if ($result['total']) {
                    return $result['total'];    
                }
                return 0;    
            }
            if (isset($result['matches'])) {
                $ids = array();
                $n = 1;
                foreach ($result['matches'] as $match) {
                    $ids[$match['id']] = $n;
                    $n++;   
                }
                $_products = ORM::factory('product')
                                ->where('id', 'IN', array_keys($ids))
                                //->where('available', '=', 1)
                                //->order_by('price', 'ASC')
                                ->find_all()
                                ->as_array();
                foreach ($_products as $product) {
                    $products[$ids[$product->id]] = $product;     
                }
                //ksort($products);
            } 
            if (isset($result['total'])) {
                $count = $result['total'];
            }   
        }
        
        return array(
            'products' => $products,
            'count'    => $count,
        );
    }
    
    public static function get_clean_params($params)
    {
        $clean_params = array();
        if ($params) {
            foreach (json_decode($params, true) as $name => $value) {
                $value = mb_strtolower(trim($value));
                $name  = mb_strtolower($name);
                
                $clean_params[] = $name.' '.$value;                         
            }
        } 
        $clean_params = implode('; ', $clean_params);
        if ($clean_params) {
            return $clean_params;
        }   
        return null;
    }
    
    public static function get_clean_search_query($query)
    {
        return str_replace(array('+', 'ё', '"'), array('', 'е', ''), $query);
    }
}
